using System; using System.Collections.Generic; using System.Linq; using System.Text; using Roslyn.Compilers; using Roslyn.Compilers.CSharp; namespace SymbolicComputation { public class Transform { public SyntaxNode matchToMe; public SyntaxNode outPattern; public delegate Boolean MatchDelegate(SyntaxNode transformMe, SyntaxNode matchToMe); public event MatchDelegate Match; public class ReplacementPair { public String TransformOperand; public String Replacement; } public static String TransformToString(Transform transform) { return transform.matchToMe.ToString() + "~" + transform.outPattern.ToString(); } public virtual String TransformString(String transformMe, String inTransform) { Transform transform = StringToTransform(inTransform); SyntaxNode equationTree = Miscellaneous.EquationToSyntaxNode(transformMe); SyntaxNode outTree = TransformSyntaxNode(equationTree, transform.matchToMe, transform.outPattern); if (outTree == null) { return ""; } return outTree.ToString(); } public virtual SyntaxNode TransformSyntaxNode(SyntaxNode transformMe, Transform transform) { return TransformSyntaxNode(transformMe, transform.matchToMe, transform.outPattern); } public virtual SyntaxNode TransformSyntaxNode(SyntaxNode transformMe, SyntaxNode matchToMe, SyntaxNode outPattern) { Boolean didMatch = MatchWalk(transformMe,matchToMe); if (didMatch == true) { return TransformMatchedSyntaxNode(transformMe, matchToMe, outPattern); } return null; } public static Transform[] StringToTransforms(String[] inTransforms) { return Functional.Maps.Map(inTransforms, StringToTransform); } public static Transform StringToTransform(String inTransform) { String[] transformStrings = Miscellaneous.Split(inTransform, "~").ToArray(); SyntaxNode[] transformTrees = Miscellaneous.EquationsToSyntaxNodes(transformStrings); Transform transform = new Transform(); transform.matchToMe = transformTrees[0]; transform.outPattern = transformTrees[1]; return transform; } public static SyntaxNode TransformMatchedSyntaxNode(SyntaxNode transformMe,SyntaxNode matchToMe, SyntaxNode outPattern) { List<ReplacementPair> ReplacementPairs = new List<ReplacementPair>(); Boolean foundMisMatch = false; GetReplacementPairs(matchToMe, transformMe, ref ReplacementPairs, ref foundMisMatch); if (foundMisMatch == false) { return ReplaceFunctions(outPattern, ReplacementPairs); } return null; } public static SyntaxNode ReplaceFunctions(SyntaxNode InTree, List<ReplacementPair> ReplacementPairs) { Int32 replacementPairIndex,descendantIndex; SyntaxNode outTree = Miscellaneous.CloneSyntaxNode(InTree); List<SyntaxNode> descendants = outTree.DescendentNodesAndSelf().ToList(); SyntaxNode clonedNode; String descendentString; for (descendantIndex = descendants.Count - 1; descendantIndex >= 0; descendantIndex--) { for (replacementPairIndex = 0; replacementPairIndex < ReplacementPairs.Count; replacementPairIndex++) { descendentString = descendants[descendantIndex].GetFullText(); if (descendentString == ReplacementPairs[replacementPairIndex].TransformOperand) { clonedNode = Miscellaneous.EquationToSyntaxNode(ReplacementPairs[replacementPairIndex].Replacement); SyntaxNode parent = descendants[descendantIndex].Parent; clonedNode = WrapNodeInBrackets(parent, clonedNode); outTree = outTree.ReplaceNode(descendants[descendantIndex], clonedNode); String test = outTree.ToString(); if (test.Contains("--") == true) { test = ""; } descendants = outTree.DescendentNodesAndSelf().ToList(); break; } } } return outTree; } public static SyntaxNode WrapNodeInBrackets(SyntaxNode parent, SyntaxNode wrapMe) { if (parent == null) { return wrapMe; } List<SyntaxNode> children; String wrapMeString = wrapMe.ToString(); if (wrapMeString.Substring(0, 1) == "-") { if (parent.Kind != SyntaxKind.EqualsExpression) { return Transform.WrapNodeInBrackets(wrapMe); } } children = parent.ChildNodes().ToList(); if (parent.Kind == SyntaxKind.SubtractExpression | parent.Kind == SyntaxKind.DivideExpression) { if (wrapMe.Kind == SyntaxKind.AddExpression | wrapMe.Kind == SyntaxKind.SubtractExpression | wrapMe.Kind == SyntaxKind.MultiplyExpression | wrapMe.Kind == SyntaxKind.DivideExpression) { return Transform.WrapNodeInBrackets(wrapMe); } } if (parent.Kind == SyntaxKind.NegateExpression) { if (wrapMe.Kind == SyntaxKind.AddExpression | wrapMe.Kind == SyntaxKind.SubtractExpression) { return Transform.WrapNodeInBrackets(wrapMe); } } if (parent.Kind == SyntaxKind.MultiplyExpression) { if (wrapMe.Kind == SyntaxKind.AddExpression | wrapMe.Kind == SyntaxKind.SubtractExpression) { return Transform.WrapNodeInBrackets(wrapMe); } } return wrapMe; } public static SyntaxNode WrapNodeInBrackets(SyntaxNode inNode) { String lStr = inNode.ToString(); lStr = "(" + lStr + ")"; return Miscellaneous.EquationToSyntaxNode(lStr); } //walk the transform tree and for each transform leaf get the matching equation in the Equation Tree public static void GetReplacementPairs(SyntaxNode matchToMe, SyntaxNode transformMe, ref List<ReplacementPair> ReplacementPairs, ref Boolean FoundMisMatch) { Int32 L; if (matchToMe.Kind == SyntaxKind.IdentifierName) { if (matchToMe.Parent.Kind != SyntaxKind.MemberAccessExpression) { Boolean ReplacementPairExists = false; //Search through the replacement pairs for (L = 0; L < ReplacementPairs.Count; L++) { if (ReplacementPairs[L].TransformOperand == matchToMe.GetFullText()) { ReplacementPairExists = true; //The transform operand matches the replacement pair if (ReplacementPairs[L].Replacement != transformMe.GetFullText()) { FoundMisMatch = true; break; } } } if (ReplacementPairExists == false) { ReplacementPair lPair = new ReplacementPair(); lPair.TransformOperand = matchToMe.GetFullText(); lPair.Replacement = transformMe.GetFullText(); ReplacementPairs.Add(lPair); } } } if (FoundMisMatch == false) { if (matchToMe.HasChildren == true) { List<SyntaxNode> matchToMeChildren = matchToMe.ChildNodes().ToList(); List<SyntaxNode> transformMeChildren = transformMe.ChildNodes().ToList(); if (transformMeChildren.Count >= matchToMeChildren.Count) { for (L = 0; L < matchToMeChildren.Count; L++) { GetReplacementPairs(matchToMeChildren[L], transformMeChildren[L], ref ReplacementPairs, ref FoundMisMatch); if (FoundMisMatch == true) { return; } } } else { FoundMisMatch = true; return; } } } } public virtual Boolean MatchWalk(SyntaxNode transformMe, SyntaxNode matchToMe) { Boolean didMatch = Match(transformMe, matchToMe); if (didMatch == false) { return false; } if (matchToMe.HasChildren == true) { Int32 L; Boolean lBool; List<SyntaxNode> matchToMeChildren = matchToMe.ChildNodes().ToList(); List<SyntaxNode> transformMeChildren = transformMe.ChildNodes().ToList(); if (matchToMeChildren.Count > 0) { if (matchToMeChildren.Count != transformMeChildren.Count) { return false; } for (L = 0; L < transformMeChildren.Count; L++) { lBool = MatchWalk(transformMeChildren[L], matchToMeChildren[L]); if (lBool == false) { return false; } } } } return true; } } }